package march
{
	import flash.utils.Dictionary;
	import march.model.ArmyStepVO;
	import march.model.PlotVO;
	import march.model.ResultVO;
	import morn.core.handlers.Handler;
	import org.airmvc.Controller;
	import org.airmvc.ModulesManager;
	import utils.T;
	import vo.CastleVO;
	import vo.GeneralVO;
	import vo.PlayerVO;
	
	/**
	 * ...
	 * @author WLDragon 2014-02-28
	 */
	public class MarchC extends Controller
	{
		
		public function MarchC()
		{
			super();
		}
		
		override protected function addListeners():void
		{
			interest(Nws.MA_MOVE, armyMove);
			interest(Nws.MA_RETREAT, retreat);
			interest(Nws.MA_ENCAMP, encamp);
			interest(Nws.MARCH_TO_SELECT_ARMY, toSelectArmy);
			interest(Nws.MA_USE_PLOT, openPlotList);
			interest(Nws.MA_ATTACK, toAttack);
			interest(Nws.FIGHT_OVER,fightOver);
			
			receive(REQUEST_TO_SELECT_ARMY, toSelectArmy);
			receive(PLACEEMENT_NEXT, placementNext);
			receive(SELECT_ARMY, selectArmy);
			receive(UPDATE_STEP, updateStep);
			receive(CHECK_ARMY, checkArmy);
			receive(RETREAT_GENERALS, retreGenerals);
			receive(USE_PLOT, usePlot);
			receive(RELEASE_PLOT, releasePlot);
			receive(CLOSE_PLOT, closePlot);
			receive(START_ATTACK,startAttack);
		}
		
		private function fightOver():void 
		{
			var i:int;
			if (curGeneral.strength <= 0)
			{
				send(ARMY_RETREAT);
				i = generalsAttack.indexOf(curGeneral);
				generalsAttack.splice(i, 1);
				if (curGeneral == captain)
				{
					//主将死亡全军撤退
					broadcast(Nws.STARTUP_GENERAL, false);
					//if(generalsAttack.length > 0)
					//{
						notEnoughCondition();
					//}
					//else
					//{
						////直接退出
					//}
					return;
				}
			}
			else if (targetGeneral.strength <= 0)
			{
				send(ARMY_RETREAT, true);
				if (targetGeneral == generalsDefense[0])
				{
					var p:PlayerVO = T.db.getRecord(Cnt.VO_PLAYER, castle.playerID) as PlayerVO;
					var g:GeneralVO;
					//防御方其余武将撤退到自身其他城或空城
					var x:XML = T.db.getXml(Cnt.XML_CASTLE).castle.(@id == castle.id)[0];
					var conList:Array = String(x.@conList).split(',');
					var arr:Array = [];
					var cid:String;
					var c:CastleVO;
					for each(cid in conList)
					{
						c = T.db.getRecord(Cnt.VO_CASTLE, int(cid));
						if (c.playerID == p.id || c.playerID == 0)
						{
							arr.push(c);
						}
					}
					var len:int = arr.length;
					if (len > 0)
					{
						for (var j:int = 1; j < generalsDefense.length; j++) 
						{
							g = generalsDefense[j];
							c = arr[Math.random() * len >> 0];
							if (c.playerID == 0)
							{
								c.playerID = p.id;
								p.castles.push(String(c.id));
								broadcast(Nws.STRATEGY_UPDATE_CASTLE,c.id,p.id);
							}
							
							c.genList.push(String(g.id));
						}
					}
					
					i = p.castles.indexOf(String(castle.id));
					p.castles.splice(i, 1);
					
					//防御方主将死亡，攻方占据城池
					castle.playerID = Gbl.activePlayer.id;
					castle.captainID = captain.id;
					castle.genList.length = 0;
					castle.gold += gold;
					castle.rice += rice;
					Gbl.activePlayer.castles.push(String(castle.id));
					broadcast(Nws.STRATEGY_UPDATE_CASTLE,castle.id,castle.playerID);
					for each(g in generalsAttack)
					{
						castle.genList.push(String(g.id));
					}
					expeditionOver();
					return;
				}
				
				i = generalsDefense.indexOf(targetGeneral);
				generalsDefense.splice(i, 1);
				i = castle.genList.indexOf(String(targetGeneral.id));
				castle.genList.splice(i,1);
			}
			
			send(SHOW_MAP);
			send(ARMY_UPDATE_SOLDIERS);
			broadcast(Nws.INFOMATION_UPDATE_ACTION, date, gold, rice, step);
			toSelectArmy();
		}
		
		/**
		 * 打开短兵相接模块
		 * @param	target 攻击对象
		 * @param	type   地型1-山 2-水 3-平原 4-森林 5-沙漠 6-城池 789村庄
		 */
		private function startAttack(target:GeneralVO,type:int = 3):void 
		{
			targetGeneral = target;
			
			step -= 2;
			Msg.instance.show("");
			broadcast(Nws.STARTUP_FIGHT, Nws.STARTUP_FIGHT, curGeneral, target, type);
			broadcast(Nws.INFOMATION_UPDATE_ACTION, 0);
			broadcast(Nws.MENU_SHOW,-2);
			//broadcast(Nws.STARTUP_GENERAL,false);
		}
		
		private function toAttack():void 
		{
			if (step >= 2)
			{
				Msg.instance.show("攻击敌方哪支部队?",125,332);
				send(READ_ATTACK);
			}
			else
			{
				Msg.instance.show("机动力不足,请执行其他命令",125,332,12,toSelectArmy);
			}
		}
		
		private function closePlot():void
		{
			broadcast(Nws.INFOMATION_UPDATE_ACTION, date, gold, rice, step);
			broadcast(Nws.MENU_SHOW, 7);
			send(SHOW_PLOT, null, true);
		}
		
		private function releasePlot(target:GeneralVO, dx:int, dy:int, type:int):void
		{
			if (curPlot.id == 5)
			{
				//伪击转杀计谋
				if (!((dx == 0 && dy == 1) || (dx == 1 && dy == 0)))
				{
					Msg.instance.show("若不能接近少许\n计谋便无法施展",130,332);
					return;
				}
			}
			else if (dx > 5 || dy > 5)
			{
				Msg.instance.show("若不能接近少许\n计谋便无法施展",130,332);
				return;
			}
			
			if (curPlot.terrain.indexOf(String(type)) == -1)
			{
				Msg.instance.show("此处请用其他计策",130,332);
				return;
			}
			
			Kyb.setOperater(null);
			//播放计谋动画
			broadcast(Nws.REPORT_PLOT_CASE, curPlot.id, target, new Handler(plotResult, [target, Math.max(dx, dy)]));
			Msg.instance.show("好,依计行事", 130, 340);
		}
		
		private function plotResult(target:GeneralVO, distance:int):void
		{
			step -= curPlot.step;
			broadcast(Nws.INFOMATION_UPDATE_ACTION, date, gold, rice, step);
			
			var dk:int = curGeneral.knowledge - target.knowledge;
			var dl:int = curGeneral.level - target.level;
			var level:int = Gbl.sys.level * 5;
			var sc:Number = ((distance - 3) * (-5) + (dk < 0 ? 0 : dk) + (dl < 0 ? 0 : dl) * 2 + level) * 0.01;
			sc = sc < 0.05 ? 0.05 : sc;
			sc = sc > 0.95 ? 0.95 : sc;
			if (Math.random() < sc)
			{
				var h:int;
				if (curPlot.id == 1 || curPlot.id == 5)
				{
					h = curGeneral.knowledge * (9 + Math.random() * 4) * 0.1 + (curGeneral.level - 1) * 10 + 30;
				}
				else if (curPlot.id == 3)
				{
					h = curGeneral.power * (14 + Math.random() * 5) * 0.1;
				}
				else if (curPlot.id == 4)
				{
					h = curGeneral.knowledge * (20 + Math.random() * 6) * 0.1 + (curGeneral.level - 1) + 7;
				}
				else if (curPlot.id == 2)
				{
					//陷阱消耗武将体力
					h = (5 + Math.random() * 2) * (curGeneral.level - 1 + (curGeneral.power + curGeneral.knowledge) * 0.1) * 0.1;
					target.strength -= h;
					if (target.strength <= 0)
					{
						Msg.instance.show("敌方武将阵已阵亡", 130, 332, 12, toSelectArmy);
						send(ARMY_RETREAT,true);
						var i:int = generalsDefense.indexOf(target);
						generalsDefense.splice(i, 1);
						i = castle.genList.indexOf(String(target.id));
						castle.genList.splice(i,1);
					}
					else
					{
						Msg.instance.show("敌方武将体力下降 " + h + "点", 130, 332, 12, toSelectArmy);
					}
					return;
				}
				
				var realH:int = (target.soliders - h) < 0 ? target.soliders : h;
				target.soliders -= realH;
				send(ARMY_UPDATE_SOLDIERS);
				Msg.instance.show("敌方军士兵减少 " + realH + "人", 130, 332, 12, toSelectArmy);
			}
			else
			{
				Msg.instance.show("计谋未能成功\n真失策", 130, 332, 12, toSelectArmy);
			}
		}
		
		private function usePlot(p:PlotVO):void
		{
			curPlot = p;
			
			Msg.instance.show("向何人施用计谋?",125,332);
			send(SELECT_PLOT_TARGET);
		}
		
		private function openPlotList():void
		{
			var arr:Array = [];
			for each (var p:PlotVO in plots)
			{
				if (curGeneral.knowledge >= p.minKnow)
					arr.push(p);
			}
			
			broadcast(Nws.INFOMATION_UPDATE_ACTION, 0);
			send(SHOW_PLOT, arr, false, step);
		}
		
		private function checkArmy(g:GeneralVO):void
		{
			Msg.instance.show("");
			broadcast(Nws.GENERAL_OPEN, [g], Cnt.MODE_MARCH);
		}
		
		private function encamp():void
		{
			for each (var g:GeneralVO in generalsAttack)
			{
				var consume:int = Cnt.CONSUME_RICE[(g.soliders / 100 >> 0)];
				if (rice >= consume)
				{
					rice -= consume;
				}
				else
				{
					rice = 0;
					broadcast(Nws.STARTUP_GENERAL, false);
					broadcast(Nws.MENU_SHOW, 0);
					Msg.instance.show("粮草不足,无法继续作战", 125, 340, 12, notEnoughCondition);
					return;
				}
			}
			
			date++;
			if (date > 30)
			{
				broadcast(Nws.STARTUP_GENERAL, false);
				broadcast(Nws.MENU_SHOW, 0);
				Msg.instance.show("一个月作战,兵士疲惫,无法继续作战", 100, 340, 12, notEnoughCondition);
				return;
			}
			
			resetStep();
			
			broadcast(Nws.INFOMATION_UPDATE_ACTION, date, gold, rice, step);
			toSelectArmy();
		}
		
		private function notEnoughCondition():void
		{
			isFollowRetreat = true;
			send(UPDATE_RESULT, resultAttack, resultDefense);
			broadcast(Nws.MARCH_TO_RETREAT);
			broadcast(Nws.INFOMATION_UPDATE_ACTION, 0);
		}
		
		private function retreGenerals(gs:Array):void
		{
			var i:int;
			var r:int;
			var c:CastleVO;
			var g:GeneralVO;
			if (retreatCastleId == 0)
			{
				//在野，武将分配到战场城池或相连的任一座城，武将忠诚度为10或90
				var xml:XML = T.db.getXml(Cnt.XML_CASTLE).castle.(@id == castle.id)[0];
				var arr:Array = String(xml.@conList).split(',');
				arr.push(String(castle.id));
				for each (g in gs)
				{
					i = generalsAttack.indexOf(g);
					generalsAttack.splice(i, 1);
					
					g.loyalty = Math.random() < 0.5 ? 10 : 90;
					
					r = Math.random() * arr.length;
					c = T.db.getRecord(Cnt.VO_CASTLE, int(arr[r]));
					c.storeList.unshift(String(g.id));
				}
			}
			else
			{
				c = T.db.getRecord(Cnt.VO_CASTLE, retreatCastleId);
				for each (g in gs)
				{
					if (g == captain)
					{
						c.rice += rice;
						c.gold += gold;
					}
					
					i = generalsAttack.indexOf(g);
					generalsAttack.splice(i, 1);
					if (g.id == Gbl.activePlayer.monarchID)
					{
						c.captainID = g.id;
						c.genList.unshift(String(g.id));
					}
					else
					{
						c.genList.push(String(g.id));
					}
				}
			}
			
			if (generalsAttack.length > 0)
			{
				send(UPDATE_RESULT, resultAttack, resultDefense);
				broadcast(Nws.MARCH_TO_RETREAT);
			}
			else
			{
				expeditionOver();
			}
		}
		
		private function expeditionOver():void
		{
			broadcast(Nws.INFOMATION_UPDATE_ACTION, 0);
			broadcast(Nws.MENU_SHOW_OR_HIDE, true);
			broadcast(Nws.INFOMATION_UPDATE_TIME, 2);
			broadcast(Nws.INFOMATION_UPDATE_ORDER, 2);
			broadcast(Nws.MENU_SHOW, 50);
			send(EXPEDITION_OVER);
		}
		
		private function toSelectArmy():void
		{
			if (step == 0)
			{
				encamp();
			}
			else
			{
				broadcast(Nws.STARTUP_GENERAL, false);
				broadcast(Nws.MENU_SHOW, 0);
				send(TO_SELECT_ARMY);
			}
		}
		
		private function retreat(castleId:int):void
		{
			var c:CastleVO = T.db.getRecord(Cnt.VO_CASTLE, castleId);
			if (c != null && c.playerID == 0)
			{
				c.playerID = Gbl.activePlayer.id;
				c.captainID = curGeneral.id;
				Gbl.activePlayer.castles.push(String(c.id));
				broadcast(Nws.STRATEGY_UPDATE_CASTLE, c.id, c.playerID);
			}
			
			if (isFollowRetreat)
			{
				//主将撤退之后
				retreatCastleId = castleId;
				
				broadcast(Nws.MENU_SHOW, 0);
				Msg.instance.show("请指定撤退之武将", 145, 340);
				send(CHOOSE_RETREAT_GENERALS, generalsAttack);
			}
			else
			{
				broadcast(Nws.MENU_SHOW, 0);
				//主将撤退之前的单人撤退(包括主将)
				if (curGeneral.id == Gbl.activePlayer.monarchID)
				{
					c.captainID = curGeneral.id;
					c.genList.unshift(String(curGeneral.id));
				}
				else
				{
					c.genList.push(String(curGeneral.id));
				}
				
				var i:int = generalsAttack.indexOf(curGeneral);
				generalsAttack.splice(i, 1);
				send(ARMY_RETREAT);
				//全军撤退
				if (curGeneral == captain)
				{
					broadcast(Nws.INFOMATION_UPDATE_ACTION, 0);
					broadcast(Nws.STARTUP_GENERAL, false);
					
					isFollowRetreat = true;
					c.gold += gold;
					c.rice += rice;
					
					var g:GeneralVO;
					g = T.db.getRecord(Cnt.VO_GENERAL, Gbl.activePlayer.monarchID);
					resultAttack.name = g.name;
					g = T.db.getRecord(Cnt.VO_GENERAL, (T.db.getRecord(Cnt.VO_PLAYER, castle.playerID) as PlayerVO).monarchID);
					resultDefense.name = g.name;
					//var sum:int = 0;
					//for each(g in generalsAttack)
					//{
					//sum += g.soliders;
					//}
					//resultAttack.lossSoldiers -= sum;
					//sum = 0;
					//for each(g in generalsDefense)
					//{
					//sum += g.soliders;
					//}
					//resultDefense.lossSoldiers -= sum;
					send(UPDATE_RESULT, resultAttack, resultDefense);
					
					if (generalsAttack.length == 0)
					{
						Msg.instance.show("战斗完成", 140, 332, 12, expeditionOver);
					}
					else
					{
						broadcast(Nws.MARCH_TO_RETREAT);
					}
				}
			}
		}
		
		/**
		 * 更新机动力
		 * @param	step 机动力
		 */
		private function updateStep(step:int):void
		{
			this.step = step;
			broadcast(Nws.INFOMATION_UPDATE_ACTION, date, gold, rice, this.step);
		}
		
		private function armyMove():void
		{
			send(ARMY_MOVE, step);
		}
		
		private function placementNext():void
		{
			if (placementIndex < generalsAttack.length)
			{
				broadcast(Nws.GENERAL_OPEN, [generalsAttack[placementIndex]], Cnt.MODE_FIGHT);
				if (placementIndex == 0)
					send(PLACEEMENT, captain, generalsDefense.length, true);
				else
					send(PLACEEMENT, generalsAttack[placementIndex], generalsDefense.length);
				
				placementIndex++;
			}
			else
			{
				broadcast(Nws.STARTUP_GENERAL, false);
				send(INIT_OVER);
			}
		}
		
		private function selectArmy(g:GeneralVO):void
		{
			curGeneral = g;
			broadcast(Nws.GENERAL_SHOW_HEAD, g.id);
			broadcast(Nws.MENU_SHOW, 7);
		}
		
		override protected function startup(... args):void
		{
			if (view == null)
			{
				//初始化视图
				view = new MarchV();
				registerView(view);
				
				var algConfig:XML = T.db.getXml(Cnt.XML_ALGORITHM);
				var plotConfig:XML = T.db.getXml(Cnt.XML_PLOT);
				
				var x:XML;
				armySteps = [];
				for each (x in algConfig.armyStep.item)
				{
					var s:ArmyStepVO = new ArmyStepVO(x.@soldiers, x.@min, x.@max);
					armySteps.push(s);
				}
				
				plots = new Dictionary();
				for each (x in plotConfig.plot)
				{
					var plotVO:PlotVO = new PlotVO();
					plotVO.id = x.@id;
					plotVO.minKnow = x.@minKnow;
					plotVO.name = x.@name + "  " + x.@step;
					plotVO.step = x.@step;
					plotVO.terrain = String(x.@terrain).split('|');
					plots[plotVO.id] = plotVO;
				}
				
				resultAttack = new ResultVO();
				resultDefense = new ResultVO();
			}
			
			generalsDefense = [];
			castle = args[1];
			generalsAttack = args[2];
			gold = args[3];
			rice = args[4];
			captain = args[5];
			date = 1;
			resetStep();
			
			//暂时只统计损失的士兵，将领以后再统计***********
			//resultAttack.lossSoldiers = 0;
			//resultDefense.lossSoldiers = 0;
			
			var g:GeneralVO;
			//for each(g in generalsAttack)
			//{
			//resultAttack.lossSoldiers += g.soliders;
			//}
			
			for each (var id:String in castle.genList)
			{
				g = T.db.getRecord(Cnt.VO_GENERAL, int(id));
				generalsDefense.push(g);
					//resultDefense.lossSoldiers += g.soliders;
			}
			
			isFollowRetreat = false;
			placementIndex = 0;
			
			broadcast(Nws.INFOMATION_UPDATE_ACTION, date, gold, rice, step);
			send(INIT_MAP, castle.id, initArmys);
		}
		
		private function resetStep():void
		{
			var sum:int = 0;
			for each (var g:GeneralVO in generalsAttack)
			{
				sum += g.soliders;
			}
			var s:ArmyStepVO;
			for each (s in armySteps)
			{
				if (sum >= s.solider)
					break;
			}
			
			step += s.min;
			step = step > s.max ? s.max : step;
		}
		
		private function initArmys():void
		{
			send(PLACE_DEFENSE, generalsDefense);
		}
		
		private var curGeneral:GeneralVO;
		private var targetGeneral:GeneralVO;
		private var castle:CastleVO;
		private var generalsAttack:Array;
		private var generalsDefense:Array;
		private var gold:int;
		private var rice:int;
		private var date:int;
		private var step:int;
		private var captain:GeneralVO;
		private var placementIndex:int;
		private var armySteps:Array;
		//private var algConfig:XML;
		private var plots:Dictionary;
		/**当前要使用的计谋*/
		private var curPlot:PlotVO;
		/**是否为主将之后的撤退*/
		private var isFollowRetreat:Boolean;
		private var resultAttack:ResultVO;
		private var resultDefense:ResultVO;
		/**记录撤退的城池id，0为在野*/
		private var retreatCastleId:int;
		
		/**初始化地图*/
		static public const INIT_MAP:String = "init_map";
		/**放置守方军队*/
		static public const PLACE_DEFENSE:String = "place_defense";
		/**地图和守方军队准备完毕*/
		//static public const MAP_READY:String = "map_ready";
		/**放置攻方军队one by one*/
		static public const PLACEEMENT:String = "placeement";
		/**放置下一个攻方军队*/
		static public const PLACEEMENT_NEXT:String = "placement_next";
		/**初始化完毕*/
		static public const INIT_OVER:String = "init_over";
		/**选择一个军队*/
		static public const SELECT_ARMY:String = "select_army";
		/**可以移动活动的军队*/
		static public const ARMY_MOVE:String = "army_move";
		/**查看军队资料*/
		static public const CHECK_ARMY:String = "check_army";
		/**更新机动数*/
		static public const UPDATE_STEP:String = "update_step";
		/**军队撤退*/
		static public const ARMY_RETREAT:String = "army_retreat";
		/**更新军队显示数量*/
		static public const ARMY_UPDATE_SOLDIERS:String = "army_update_soldiers";
		/**开始选择执行命令的军队*/
		static public const TO_SELECT_ARMY:String = "to_select_army";
		/**请求开始选择执行命令的军队*/
		static public const REQUEST_TO_SELECT_ARMY:String = "request_to_select_army";
		/**显示战斗结果*/
		static public const UPDATE_RESULT:String = "update_result";
		/**选择在主将撤退后撤退的武将*/
		static public const CHOOSE_RETREAT_GENERALS:String = "choose_retreat_generals";
		/**撤掉主将撤退后的武将*/
		static public const RETREAT_GENERALS:String = "retreat_generals";
		/**出征结束，释放资源*/
		static public const EXPEDITION_OVER:String = "expedition_over";
		/**显示计谋面板*/
		static public const SHOW_PLOT:String = "show_plot";
		/**使用计谋*/
		static public const USE_PLOT:String = "use_plot";
		/**选择一个使用计谋的目标*/
		static public const SELECT_PLOT_TARGET:String = "select_plot_target";
		/**施展计谋*/
		static public const RELEASE_PLOT:String = "release_plot";
		/**撤消技能使用*/
		static public const CLOSE_PLOT:String = "close_plot";
		/**准备攻击*/
		static public const READ_ATTACK:String = "read_attack";
		/**进入攻击*/
		static public const START_ATTACK:String = "start_attack";
		/**显示地图*/
		static public const SHOW_MAP:String = "show_map";
	}

}